Skip to content

fix: export serialization + load_some resilience (closes #4)#5

Merged
deucalioncodes merged 4 commits intomainfrom
fix/export-serialization-issue-4
Mar 21, 2026
Merged

fix: export serialization + load_some resilience (closes #4)#5
deucalioncodes merged 4 commits intomainfrom
fix/export-serialization-issue-4

Conversation

@deucalioncodes
Copy link
Copy Markdown
Member

Summary

Fixes #4 — Robust JSON serialization/deserialization with lazy relation resolution.

Changes

serialize(for_export=True) — new parameter on Entity.serialize():

  • Skips OneToMany relations (always reconstructed from reverse ManyToOne during import)
  • Serializes OneToOne on one deterministic side only: the entity whose type name is alphabetically ≤ the target type carries the reference. This eliminates circular references in exported JSON.
  • Default for_export=False preserves full backward compatibility for internal storage.

load_some() resilience:

  • Catches ValueError/AttributeError per entity during batch loading
  • Skips entities with broken/dangling relation refs instead of crashing the entire query
  • Logs a warning for each skipped entity

Tests

8 new tests in test_serialization.py:

  • test_serialize_for_export_skips_one_to_many
  • test_serialize_for_export_one_to_one_deterministic
  • test_serialize_for_export_round_trip
  • test_serialize_for_export_many_to_many
  • test_issue4_bidirectional_one_to_one_import_order — reproduces the exact User↔Member crash
  • test_issue4_one_to_many_dangling_refs_load_some — reproduces Token→WalletBalance crash
  • test_issue4_for_export_eliminates_dangling_one_to_many — proves export prevents dangling
  • test_issue4_full_round_trip_bidirectional — end-to-end Realm→User→Human→Member round-trip

…oses #4)

- serialize(for_export=True) skips OneToMany relations (reconstructed from
  reverse ManyToOne) and serializes OneToOne only on one deterministic side
  (alphabetically-earlier entity type carries the reference).
  This prevents circular/dangling references in exported JSON.

- load_some() now catches ValueError/AttributeError per entity, skipping
  broken entities with dangling relation refs instead of crashing the batch.

- 8 new tests: 4 for for_export behavior + 4 issue #4 regression tests
  covering bidirectional OneToOne import, OneToMany dangling refs,
  export-eliminates-dangling, and full round-trip.
…y and picks one side of OneToOne

Breaking change (no production use yet): serialize() now always produces
clean output without OneToMany relations and with deterministic OneToOne
side selection. This simplifies the API — callers no longer need to pass
for_export=True.

Updated all tests to match new default behavior.
…r persistence)

serialize() skips OneToMany and picks one side of OneToOne — safe for
export/import without circular refs.

_serialize_full() preserves all relations — used by _save() so internal
persistence (load/save cycles) keeps working correctly.

_serialize_base() and _get_entity_reference() are shared helpers.
@deucalioncodes deucalioncodes merged commit 84ff23f into main Mar 21, 2026
5 checks passed
@deucalioncodes deucalioncodes deleted the fix/export-serialization-issue-4 branch March 21, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Robust JSON serialization/deserialization with lazy relation resolution

1 participant